/*
  3D - C++ Class Library for 3-D Rigid Transformations
  Copyright (C) 1996, 1997  Gino van den Bergen

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

  Please send remarks, questions and bug reports to gino@win.tue.nl,
  or write to:
                  Gino van den Bergen
		  Department of Mathematics and Computing Science
		  Eindhoven University of Technology
		  P.O. Box 513, 5600 MB Eindhoven, The Netherlands
*/

#ifndef _POINT_H_
#define _POINT_H_

#include "Vector.h"

class Point : public Vector {
public:
  Point() {}
  Point(const float p[3]) : Vector(p) {} 
  Point(const double p[3]) : Vector(p) {}
  Point(Scalar x, Scalar y, Scalar z) : Vector(x, y, z) {}

  Point& operator+=(const Vector& v);
  Point& operator-=(const Vector& v);
  Point& operator*=(Scalar s);
  Point& operator/=(Scalar s);

  void setInf(const Point& p);
  void setSup(const Point& p);
};

Point operator+(const Point& p, const Vector& v);
Point operator-(const Point& p, const Vector& v);
Point operator*(const Point& p, Scalar s);
Point operator*(Scalar s, const Point& p);
Point operator/(const Point& p, Scalar s);

int operator<(const Point& p1, const Point& p2);
Point inf(const Point& p1, const Point& p2);
Point sup(const Point& p1, const Point& p2);

Scalar distance(const Point& p1, const Point& p2);
Scalar distance2(const Point& p1, const Point& p2);



inline Point& Point::operator+=(const Vector& v) {
  coor[X] += v[X]; coor[Y] += v[Y]; coor[Z] += v[Z];
  return *this;
}

inline Point& Point::operator-=(const Vector& v) {
  coor[X] -= v[X]; coor[Y] -= v[Y]; coor[Z] -= v[Z];
  return *this;
}

inline Point& Point::operator*=(Scalar s) {
  coor[X] *= s; coor[Y] *= s; coor[Z] *= s;
  return *this;
}

inline Point& Point::operator/=(Scalar s) {
  coor[X] /= s; coor[Y] /= s; coor[Z] /= s;
  return *this;
}

inline void Point::setInf(const Point& p) {
  set_min(coor[X], p[X]); 
  set_min(coor[Y], p[Y]); 
  set_min(coor[Z], p[Z]);
}

inline void Point::setSup(const Point& p) {
  set_max(coor[X], p[X]); 
  set_max(coor[Y], p[Y]); 
  set_max(coor[Z], p[Z]);
}

inline Point operator+(const Point& p, const Vector& v) {
  return Point(p[X] + v[X], p[Y] + v[Y], p[Z] + v[Z]);
}

inline Point operator-(const Point& p, const Vector& v) {
  return Point(p[X] - v[X], p[Y] - v[Y], p[Z] - v[Z]);
}

inline Vector operator-(const Point& p1, const Point& p2) {
  return Vector(p1[X] - p2[X], p1[Y] - p2[Y], p1[Z] - p2[Z]);
}

inline Point operator*(const Point& p, Scalar s) {
  return Point(p[X] * s, p[Y] * s, p[Z] * s);
}

inline Point operator*(Scalar s, const Point& p) { return p * s; }

inline Point operator/(const Point& p, Scalar s) {
  return Point(p[X] / s, p[Y] / s, p[Z] / s);
}

inline int operator<(const Point& p1, const Point& p2) {
  return p1[X] < p2[X] && p1[Y] < p2[Y] && p1[Z] < p2[Z];
}

inline Point inf(const Point& p1, const Point& p2) {
  return Point(min(p1[X], p2[X]), min(p1[Y], p2[Y]), min(p1[Z], p2[Z]));
}

inline Point sup(const Point& p1, const Point& p2) {
  return Point(max(p1[X], p2[X]), max(p1[Y], p2[Y]), max(p1[Z], p2[Z]));
}

inline Scalar distance(const Point& p1, const Point& p2) { 
  return length(p1 - p2); 
}

inline Scalar distance2(const Point& p1, const Point& p2) { 
  return length2(p1 - p2); 
}


#endif
